#!/usr/bin/env python
#coding: iso-8859-1


import bullet
from direct.actor import Actor
from direct.interval.IntervalGlobal import *
from direct.particles.ForceGroup import ForceGroup
from direct.particles.ParticleEffect import ParticleEffect
from direct.particles.Particles import Particles
import globals
from panda3d.physics import BaseParticleEmitter
from panda3d.physics import BaseParticleRenderer
from panda3d.physics import DiscEmitter
from panda3d.physics import LinearNoiseForce
from panda3d.physics import PointParticleFactory
from panda3d.physics import SpriteParticleRenderer
from pandac.PandaModules import *
from pandac.PandaModules import CollisionNode
from pandac.PandaModules import CollisionSphere
import spotlight
from direct.showbase.DirectObject import DirectObject

from input.XboxControllerHandler import XboxControllerHandler

import score

class Player(DirectObject):
    def __init__(self, model):
        self.idle_anim = None
        self.run_anim = None
        self.attack_anim = None
        self.dead_anim = None
        self.hit_anim = None
        self.model = model
        self.life = 0.0
        self.TOP_LIFE = 1.0
        self.lives = 3
        self.plight_att = 0.05
        self.score = None
        self.actor = Actor.Actor()
        self.actor.loadModel(self.model)
        self.explosion = None
        self.shot_count = 0.0;
        self.light_count = 1.0;

        #SPOTLIGHT TEXTURE
        self.spotactor = spotlight.spotlightTexture()
        self.spotactor.init()
        self.spotactor.actor.reparentTo(self.actor)

    def shot(self):
        if self.shot_count == 5:
            bullet.Bullet(Point3(globals.PlayerPosition.getX()+8000,globals.PlayerPosition.getY(),globals.PlayerPosition.getZ()),
                        Point3(Point3(globals.PlayerPosition.getX(),globals.PlayerPosition.getY(),globals.PlayerPosition.getZ())))
            self.shot_count = 0


            
    def ih_left(self,rate):
        if(self.actor.getY() < 100.0):
            self.actor.setX(self.actor, float(self.TIMES * rate * globalClock.getDt()))

    def ih_right(self,rate):
        if(self.actor.getY() > -100.0):
            self.actor.setX(self.actor,float(self.TIMES * rate * globalClock.getDt()))

    def ih_up(self,rate):
        if(self.actor.getZ() < 100.0):
            self.actor.setZ(self.actor,self.TIMES * rate * globalClock.getDt())

    def ih_down(self, rate):
        if(self.actor.getZ() > -100.0):
            self.actor.setZ(self.actor, self.TIMES * rate * globalClock.getDt())
            
            
    def init(self):

        #self.keyInput = KeyboardMouseHandler()
        self.xboxInput = XboxControllerHandler()

        self.accept("up", self.ih_up)
        self.accept("down", self.ih_down)
        self.accept("left", self.ih_left)
        self.accept("right", self.ih_right)
        self.accept("shot", self.shot)

        
        
        self.score = score.Score()
        self.node = render.attachNewNode("Jugador")

        #Setting scale and position to the model
        self.actor.setScale(Point3(1, 1, 1))
        self.actor.setPos(Point3(0, 0, 0))
        self.actor.setH(90)
        self.actor.reparentTo(self.node)

        
        self.actor.loadAnims({"idle":self.idle_anim})
        self.actor.loadAnims({"run":self.run_anim})
        self.actor.loadAnims({"attack":self.attack_anim})
        self.actor.loadAnims({"dead":self.dead_anim})
        self.actor.loadAnims({"hit":self.hit_anim})
        self.actor.bindAnim('run')

        self.actor.bindAnim('run')
        self.actor.loop('run')
        self.actor.setPlayRate(1.5 + (globals.RATE - 1), 'run')

        self.cNode = CollisionNode('Player')
        self.cNode.setFromCollideMask(BitMask32.bit(1))
        self.cNode.setIntoCollideMask(BitMask32.allOff())
        self.cNode.addSolid(CollisionSphere(0, 0, 0, 13.0))
        self.frowneyC = self.actor.attachNewNode(self.cNode)
        #self.frowneyC.show()
        #base.cTrav.showCollisions(render)
        globals.WORLD.accept('into-enemyMidiCol', self.collide)
        globals.WORLD.accept('into-friendMidiCol', self.collide2)
        base.cTrav.addCollider(self.frowneyC, globals.PhysicsBox)

        self.score.setPlayer(self)
        globals.PLAYER = self.actor


        #A LIGHT FOR THE SHIP
        self.shiplight = PointLight("ShipLight")
        #set the numbers here for Red, Green, Blue for light color
        self.shiplight.setColor(Vec4(0.2, 0.2, 0.1, 1))
        self.shiplight.setSpecularColor(VBase4(0.08, 0.08, 0.07, 0.1))
        self.sequence = Sequence()
        self.shiplight.setAttenuation(Vec3(0.000171, 0.0001, 0.0008))
        self.shiplightNP = render.attachNewNode(self.shiplight)
        render.setLight(self.shiplightNP)
        #self.shiplight.setAttrib(LightRampAttrib.makeHdr())
        self.shiplightNP.reparentTo(self.node)
       
        #Point light bullet
        self.plight = PointLight("Light")
        #set the numbers here for Red, Green, Blue for light color
        self.plight.setColor(Vec4(0.9, 0.9, 0.8, 1))
        self.plight.setSpecularColor(VBase4(0.08, 0.08, 0.07, 1))
        self.plight.setAttenuation(Vec3(0.07, 0.0, 0.000005))
        self.plightNP = render.attachNewNode(self.plight)
        render.setLight(self.plightNP)
        globals.MISSIL_LIGHT_POSITION = self.plightNP
        self.plight.setAttrib(LightRampAttrib.makeHdr2())
        self.dummyNode = render.attachNewNode("Dummy Node Name")
        self.dummyNode.setPos(10000,10000,10000)

        #SPOTLIGHT OR PLAYER HEADLIGHT
        self.slight = Spotlight('slight')
        #print dir(slight)
        self.slight.setColor(VBase4(0.91, 0.91, 0.91, 1))
        self.slight.setSpecularColor(VBase4(0.08, 0.08, 0.07, 0.1))
        lens = PerspectiveLens()
        lens.setFov(30, 30)
        lens.setNearFar(10, 4500)
        #self.slight.showFrustum()
        self.slight.setLens(lens)
        self.slight.setExponent(120)
        self.slight.setAttenuation(Vec3(0.05, 0.0, 0.0))
        #self.slight.setShadowCaster(True,1024,1024)
        self.plnp = render.attachNewNode(self.slight)
        self.plnp.setHpr(150, 150, 150)
        self.plnp.lookAt(5,0, 0)
        render.setShaderInput("light", self.plnp)
        render.setLight(self.plnp)
        #self.slight.setInitialState(RenderState.make(CullFaceAttrib.makeReverse(), ColorWriteAttrib.make(ColorWriteAttrib.COff)))

 

        #self.explosion.reparentTo(self.node)
        #SMOKE PARTICLE FROM MOTOR
        self.p = ParticleEffect()
        self.p.reset()
        self.p.setPos(0.000, 17.000, 0.000)
        self.p.setHpr(0.000, 0.000, 0.000)
        self.p.setScale(1.000, 1.000, 1.000)

        self.p0 = Particles('particles-1')
        # Particles parameters
        self.p0.nodePath.setShaderOff()
        self.p0.setFactory("PointParticleFactory")
        self.p0.setRenderer("SpriteParticleRenderer")
        self.p0.setEmitter("SphereSurfaceEmitter")
        self.p0.setPoolSize(256)
        self.p0.setBirthRate(0.0500)
        self.p0.setLitterSize(14)
        self.p0.setLitterSpread(1)
        self.p0.setSystemLifespan(0.0000)
        self.p0.setLocalVelocityFlag(1)
        self.p0.setSystemGrowsOlderFlag(0)
        self.p0.factory.setLifespanBase(0.15000)
        self.p0.factory.setLifespanSpread(0.500)
        self.p0.factory.setMassBase(2.0000)
        self.p0.factory.setMassSpread(0.0100)
        self.p0.factory.setTerminalVelocityBase(400.0000)
        self.p0.factory.setTerminalVelocitySpread(0.0000)
        self.p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT)
        self.p0.renderer.setUserAlpha(0.53)
        self.p0.renderer.setTexture(loader.loadTexture('../data/lvl/level1/cha/smoke.png'))
        self.p0.renderer.setColor(Vec4(1.00, 1.00, 1.00, 1.00))
        self.p0.renderer.setXScaleFlag(1)
        self.p0.renderer.setYScaleFlag(1)
        self.p0.renderer.setAnimAngleFlag(1)
        self.p0.renderer.setInitialXScale(0.02500)
        self.p0.renderer.setFinalXScale(0.000)
        self.p0.renderer.setInitialYScale(0.02500)
        self.p0.renderer.setFinalYScale(0.0000)
        self.p0.renderer.setNonanimatedTheta(0.0000)
        self.p0.renderer.setAlphaBlendMethod(BaseParticleRenderer.PPBLENDLINEAR)
        self.p0.renderer.setAlphaDisable(0)
        self.p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE)
        self.p0.emitter.setAmplitude(1.0000)
        self.p0.emitter.setAmplitudeSpread(1.0000)
        self.p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 1.0000))
        self.p0.emitter.setExplicitLaunchVector(Vec3(1.0000, 0.0000, 0.0000))
        self.p0.emitter.setRadiateOrigin(Point3(0.2000, 1.0000, 0.5000))
        self.p0.emitter.setRadius(0.0300)
        self.p.addParticles(self.p0)
        f0 = ForceGroup('gravity')
        force0 = LinearNoiseForce(5.4007, 0)
        force0.setVectorMasks(1, 1, 0)
        force0.setActive(1)
        f0.addForce(force0)
        force1 = LinearVectorForce(Vec3(0.0000, 600.0000, 10.0000), 1.0000, 0)
        force1.setVectorMasks(1, 1, 1)
        force1.setActive(1)
        f0.addForce(force1)
        self.p.addForceGroup(f0)
        self.p.start(self.actor)
        self.p0.renderer.setUserAlpha(self.life*0.5)
        self.p0.renderer.setFinalXScale(self.life*0.125)
        self.p0.renderer.setFinalYScale(self.life*0.125)
        self.p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 1.0000+self.life*0.65))



        globals.BIGBOSS = "life:" + str(self.life)


        self.camTask = taskMgr.add(self._update, 'Player-Follow')
        self.camTask.last = 0

        self.TIMES = 100.0
        self.rotation = -1

        self.accept("z", self.light,[0.21])
        self.accept("x", self.light,[-0.21])

        self.accept("c-up", self.rota,[0.121])
        self.accept("v-up", self.rota,[-0.121])

        taskMgr.doMethodLater(0.2,self.lightDownCB,'lightDownCB')
        
    def rota(self,value):
        self.rotation += value
        print self.rotation

    def light(self,value):
        taskMgr.remove('lightDownCB')
        self.plight_att += value
        self.slight.setColor(Vec4(self.plight_att,self.plight_att,self.plight_att, 1))
        self.slight.setSpecularColor(Vec4(self.plight_att*0.01,self.plight_att*0.01,self.plight_att*0.01, 1))
        print self.plight_att


    #player update cycle / keyboard events and light positions
    def _update(self, task):
        #       SHIP POINT LIGHT FLASHING SEQUENCE
        if not self.sequence.isPlaying():
            self.sequence = Sequence(
                                    self.shiplightNP.colorInterval(0.2,VBase4(1, 1, 0.0, 1),VBase4(1, 0.0, 0.0, 1)),
                                    self.shiplightNP.colorInterval(0.2,VBase4(1, 1, 0.0, 1),VBase4(1, 0.0, 0.0, 1)),
                                    self.shiplightNP.colorInterval(0.2,VBase4(1, 1, 0.0, 1),VBase4(1, 0.0, 0.0, 1)))
            self.sequence.loop()

#       LIGHT POSITION CONTROL FOR POINT LIGHT MISSILE
        if globals.BULLET == 0:
            globals.MISSIL_LIGHT_POSITION.reparentTo(self.dummyNode)

        globals.PlayerPosition = self.actor.getPos()

        #SPOT LIGHT POSITION CHANGED EACH CYCLE TO PLAYER POS
        #self.plnp.setPos(Point3(globals.PlayerPosition.getX() +10, globals.PlayerPosition.getY(), globals.PlayerPosition.getZ()))
        #self.plnp.lookAt(Point3(globals.PlayerPosition.getX() +100, globals.PlayerPosition.getY(), globals.PlayerPosition.getZ()+self.rotation)
        self.plnp.setPos(Point3(globals.PlayerPosition.getX() + 10, globals.PlayerPosition.getY(), globals.PlayerPosition.getZ()))
        self.plnp.lookAt(Point3(globals.PlayerPosition.getX() + 15, globals.PlayerPosition.getY(), globals.PlayerPosition.getZ()+self.rotation))

        self.shiplightNP.setPos(Point3(globals.PlayerPosition.getX()-25, globals.PlayerPosition.getY(), globals.PlayerPosition.getZ()+5))
        self.shiplight.setColor(self.shiplightNP.getColor())
        return task.cont

    def lightDownCB(self,task):
            if self.light_count > 0:
                self.light_count -= 0.023
            else:
                self.light_count = 0.00125
            self.plight_att = self.light_count
            self.slight.setColor(Vec4(self.plight_att,self.plight_att,self.plight_att, 1))
            self.slight.setSpecularColor(Vec4(self.plight_att*0.01,self.plight_att*0.01,self.plight_att*0.01, 1))
            #print globals.collCount

            taskMgr.doMethodLater(0.35,self.lightDownCB,'lightDownCB')
            return task.done

    def collide2(self, collEntry):
        obj = collEntry.getIntoNodePath().getParent()
        enemy_name = obj.getNetTag('enemy')
        
        if enemy_name:
            obj = globals.ENEMIES[enemy_name]
            if obj != None and hasattr(obj, 'die'):
                obj.die(self)
                #print enemy_name
            
    def collide(self, collEntry):
        if globals.LIFE < 1:
            self.die()

        #print self.life, globals.LIFE
        obj = collEntry.getIntoNodePath().getParent()
        enemy_name = obj.getNetTag('enemy')
        if enemy_name:
            obj = globals.ENEMIES[enemy_name]
            #print obj
            #If it was found, then kill the enemy
            if obj != None and hasattr(obj, 'die'):
                obj.die(self)
                #print enemy_name

            #print self.life, globals.LIFE, self.plight_att
            if(self.life < self.TOP_LIFE):
                self.p0.renderer.setUserAlpha(0.0001+(self.life)*0.5)
                self.p0.renderer.setFinalXScale(0.0001+(self.life)*0.125)
                self.p0.renderer.setFinalYScale(0.0001+(self.life)*0.125)
                self.p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 1.0000+(self.life*17.5)*0.85))
                globals.BIGBOSS = "life:" + str(self.life) + " lives:" + str(self.lives)


    def die(self):
        globals.LIFE = 10
        self.life = 0.0
        self.lives -= 1
        if self.lives == 0:
            print "GameOver"
            self.lives = 3

    def restartLight(self):
        taskMgr.remove('lightDownCB')
        taskMgr.doMethodLater(0.35,self.lightDownCB,'lightDownCB')
